home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / gfx / conv / ilbm24.lha / ilbm / writeilbm.c < prev    next >
C/C++ Source or Header  |  1993-02-12  |  7KB  |  227 lines

  1. /*
  2.  *  Writeilbm.c
  3.  *
  4.  *  Writes out a 24 bit IFF ILBM file, compressed or uncompressed from a 24 or 32 bit
  5.  *  Sun Raster file.
  6.  *  By Brett Van Sprewenburg
  7.  * 
  8.  *  A nice addition would be to convert regular 8 bit rasters to 24 bit, then write the ilbm.
  9.  *  (see version 1.4, hehe)
  10.  *
  11.  *  Credit to the ppm utilities, the developer(s) of xv, and Commodore-Amiga for
  12.  *  code and ideas.
  13.  *
  14.  * Version
  15.  *   1.0     2/1/93    First working version, with hardcoded form and body chunk sizes.
  16.  *            Only uncompressed images work.
  17.  *   1.1    2/2/93    Added in the correct form and body sizes with compression by altering
  18.  *            the file after it was written.
  19.  *
  20.  *   1.2    2/4/93    First working version with compression done correctly. I still wouldn't
  21.  *            be able to tell you exactly what was wrong. Fixed multiple things with
  22.  *            readilbm integration. The biggest problem with this version is that it's sloooow.
  23.  *              A faster way may be to do 8 planes at once, instead of a plane at a time.
  24.  *   1.3    2/9/93  Fixed previous slowness by compiling with acc -fast. ANIS'fied code also for 
  25.  *            compilation with acc without warnings.
  26.  *   1.4    2/10/93 Added reading and conversion of 8 bit rasters into 24 bit ilbms.
  27.  *   1.4.1    2/12/93    Checked that memeory allocations succeded.
  28.  *            First public release.
  29.  */
  30.  
  31. #include <writeilbm.h>
  32.  
  33. int WriteILBM(char *, int);
  34.  
  35. extern byte *pic;          /* Pointer to pixel interleaved raster */
  36.                   /* Or index into cmap if < 24 bit planes */
  37. extern byte r[255],g[255],b[255]; /* Said cmap */
  38.  
  39. int WriteILBM(char *ilbmfile, int compression)
  40. {
  41.   FILE *fp;
  42.   long formsize,bmhdsize,bodysize;
  43.   byte *coded_rowbuf,*cp,*raw_rowbuf;
  44.   int rel_count,rgbline,linesize,mask,yoffset,offset,push;
  45.   register int row, col, plane;
  46.   unsigned int bit;
  47.   static byte *image,*hpic,*ebitimage,*tpic;
  48.   int pad,tot_bytes,packedbytes,ycoffset,coffset,ccol = 0;
  49.  
  50.   tot_bytes = packedbytes = 0;
  51.  
  52.   if ((fp = fopen(ilbmfile,"w")) == NULL) {
  53.     fprintf(stderr,"Open of '%s' for writing failed.\n",ilbmfile); 
  54.     return -1;
  55.   }
  56.  
  57.   /* I'm fairly certain that I can't handle an odd sized bitmap, so I'll just turn 'em away */
  58.   if ((sunheader.ras_width % 8) != 0) {
  59.     fprintf(stderr,"Width of '%d' is not gonna work. Must be multiple of 8.\n",sunheader.ras_width);
  60.     fclose(fp);
  61.     return -1;
  62.   }
  63.  
  64.   if (sunheader.ras_depth < 24) {    /* Convert 8 to 24 bits */
  65.      if (sunheader.ras_maptype != RMT_EQUAL_RGB) {
  66.        fprintf(stderr,"Unknown colormap type.  Save from 'xv' and try again.\n");
  67.        fclose(fp);
  68.        return -1;
  69.      }
  70.      tpic = pic;
  71.      fprintf(stderr,"Converting Sun Raster to 24 bit planes.\n");
  72.      hpic = (byte *)malloc(sunheader.ras_height * sunheader.ras_width * 3);
  73.      if (hpic == NULL) {
  74.     fprintf(stderr,"Can't get the memory I need...\n");
  75.     fclose(fp);
  76.     return -2;
  77.      }
  78.      ebitimage = hpic; 
  79.  
  80.      for (row = 0; row < (int)sunheader.ras_height; row++) {
  81.     yoffset = row * sunheader.ras_width;
  82.      ycoffset = row * (sunheader.ras_width * 3);
  83.        for (col = 0; col < (int)sunheader.ras_width; col++) {
  84.      offset = yoffset + col;
  85.       coffset = ycoffset + ccol;
  86.      *(hpic + coffset) = r[*(tpic + offset)];
  87.      coffset++;
  88.      *(hpic + coffset) = g[*(tpic + offset)];
  89.      coffset++;
  90.      *(hpic + coffset) = b[*(tpic + offset)];
  91.      ccol+=3;
  92.      if (ccol == (sunheader.ras_width * 3))
  93.        ccol = 0;
  94.        }
  95.      }
  96.      pic = ebitimage;
  97.   }
  98.  
  99.   /* Assign information to ilbm header */
  100.   /* See AmigaDOS hardware RKM for more info */
  101.   ilbmheader.w = (unsigned short)sunheader.ras_width;
  102.   ilbmheader.h = (unsigned short)sunheader.ras_height;
  103.   ilbmheader.x = 0;
  104.   ilbmheader.y = 0;
  105.   ilbmheader.nPlanes = 24;        /* We're only going to write 24 bit IFF's */
  106.   ilbmheader.masking = mskNone;
  107.   if (compression) {
  108.     ilbmheader.compression = cmpByteRun1;
  109.     printf("Compression On.\n");
  110.   } else
  111.     ilbmheader.compression = cmpNone;
  112.   ilbmheader.pad1 = 0;
  113.   ilbmheader.transparentColor = 0;
  114.   ilbmheader.xAspect = 10;
  115.   ilbmheader.yAspect = 10;
  116.   ilbmheader.pageWidth = (unsigned short)sunheader.ras_width ;
  117.   ilbmheader.pageHeight = (unsigned short)sunheader.ras_height;
  118.  
  119.   /* Full pixel interleaved line consists of tuplets of rgb values */
  120.   rgbline = ilbmheader.w * 3; 
  121.   coded_rowbuf = (byte *)malloc(ilbmheader.w);
  122.   raw_rowbuf = (byte *)malloc(rgbline);
  123.   if (coded_rowbuf == NULL || raw_rowbuf == NULL) {
  124.     fprintf(stderr,"Can't get the memory I need...\n");
  125.     fclose(fp);
  126.     return -2;
  127.   }
  128.  
  129.   /* RoyBytes fromula from ilbm.h */
  130.   linesize = RowBytes(ilbmheader.w);
  131.   bmhdsize = sizeof(struct BitMapHeader);
  132.   if (!compression) {
  133.     bodysize = ilbmheader.h * linesize * ilbmheader.nPlanes;
  134.     formsize = 4 + 4 + 4 + bmhdsize + 4 + 4 + bodysize;
  135.   } else {
  136.     bodysize = 999999;        
  137.     formsize = 999999;        /* Do this because we don't know how much compression we'll get */
  138.   }
  139.  
  140.   fwrite("FORM",4,1,fp);
  141.   fwrite(&formsize,4,1,fp);
  142.   fwrite("ILBM",4,1,fp);
  143.   fwrite("BMHD",4,1,fp);
  144.   fwrite(&bmhdsize,4,1,fp);
  145.   fwrite(&ilbmheader,bmhdsize,1,fp);
  146.   fwrite("BODY",4,1,fp);
  147.   fwrite(&bodysize,4,1,fp);
  148.  
  149.   image = raw_rowbuf;           /* Hold this pointer to the raw buffer in image pointer */
  150.  
  151.   /* This next whole thing took quite a while to figure out 
  152.    This file format looks like this:  ( all data is bit reversed )
  153.    Plane       data             scanline
  154.    -------------------------------------------
  155.    Plane 0:    RowBytes of red        0
  156.    Plane 1:    RowBytes of red        0
  157.      |
  158.    Plane 7:    RowBytes of red        0
  159.    Plane 8:    RowBytes of green    0
  160.      |
  161.    Plane 15:    RowBytes of green    0
  162.    Plane 16:    RowBytes of blue    0
  163.      |
  164.    Plane 23:    RowBytes of blue    0
  165.    Plane 0:    RowBytes of red        1
  166.    Plane 1:    RowBytes of red        1
  167.       and the beat goes on...
  168.   */
  169.  
  170.   /* Figure this next bit out for yourself :-<  */
  171.  
  172.   for (row = 0;row < (int)ilbmheader.h;row++) {
  173.     yoffset = row * rgbline;
  174.     raw_rowbuf = image;
  175.     for (plane = 0 ;plane < (int)ilbmheader.nPlanes; plane++) {
  176.       if (plane < 8) {
  177.     push = plane;
  178.       } else if (plane > 15) {
  179.         push = plane - 16;
  180.       }
  181.       else {
  182.     push = plane - 8;
  183.       }
  184.         mask = 1 << push;        /* how many bits to push */
  185.       cp = coded_rowbuf;
  186.       *cp = 0;
  187.       for (col = (plane / 8), rel_count = 0 ; col < rgbline; rel_count++ ,col+=3) {
  188.       offset = yoffset + col;
  189.         bit = (*(pic + offset) & mask) ? 1 : 0;
  190.       *cp |= bit << ( 7 - (rel_count % 8) );
  191.     if ((rel_count % 8)  == 7) {    /* Every 8th byte, advance pixel */
  192.       cp++;
  193.       *cp = 0;
  194.         }
  195.       }
  196.       if (compression) {    /* This bit is pretty obvious. */
  197.         raw_rowbuf = image;    /* compression is rle, as specified in AmigaDOS 2.0 RKM */
  198.     packedbytes = packrow(coded_rowbuf, raw_rowbuf, linesize);
  199.     tot_bytes+=packedbytes;
  200.     fwrite(raw_rowbuf, packedbytes, 1, fp);
  201.       } else            /* Write uncompressed data */
  202.         fwrite(coded_rowbuf, linesize, 1, fp);
  203.     }
  204.   }
  205.   if (compression) {
  206.     fclose(fp);            /* close because we must alter the fopen flags */
  207.       if ((fp = fopen(ilbmfile,"r+")) == NULL) {
  208.           fprintf(stderr,"Open of '%s' for rewriting failed.\n",ilbmfile);
  209.         return -1;            /* Hack in the real bodysize and formsize values */
  210.       }
  211.     formsize = tot_bytes + ILBMHSIZE;/* 40 is the number of bytes in the header after FORM and size */
  212.     fseek(fp,4L,0);
  213.     fwrite(&formsize,4,1,fp);
  214.     fseek(fp,44L,0);
  215.     fwrite(&tot_bytes,4,1,fp);
  216.   }
  217.   if ((tot_bytes % 2) != 0) {        /* Pad the body chunk out to an even byte */
  218.     fseek(fp,0L,2);
  219.     pad = 0;
  220.     fwrite(&pad,1,1,fp); 
  221.   }
  222.   fclose(fp);
  223.   free(coded_rowbuf);
  224.   free(raw_rowbuf);
  225.   return 0;
  226. }
  227.